home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #2 / Monster Media No. 2 (Monster Media)(1994).ISO / prog_gen / gcoope10.zip / OBJECT.C < prev    next >
Text File  |  1994-07-22  |  11KB  |  446 lines

  1. /*
  2.  
  3.     Object pseudo class definition for GCOOPE Version 1.0
  4.  
  5.             by Brian Lee Price
  6.  
  7.     Released as Public Domain   July, 1994.
  8.  
  9.     This is the pseudo-class definition for the base object
  10.     'Object'  [this is termed a pseudo class definition because
  11.     it makes use of low level kernel functions to install itself,
  12.     unlike a 'real' class definition which will use the program
  13.     interface kernel routines]
  14.  
  15. */
  16.  
  17. #define __OBJECT_DEFINITION__
  18.  
  19. #include "gcstruct.h"
  20.  
  21. #include <stdarg.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <mem.h>
  25. #include <ctype.h>
  26.  
  27. /* the pseudo class definition for Object */
  28.  
  29. static classEntry       obj;
  30.  
  31. /* first define the methods */
  32.  
  33. /* note that there is no default method for New */
  34.  
  35. /*
  36. AVAILABLE AS DEFAULT Kill routine.
  37.  
  38.     This routine will take the place of a missing class's kill
  39.     routine as well as actually killing off the object when all the
  40.     proper conditions are met.
  41. */
  42.  
  43. static object kill(object instance,...)
  44. {
  45. va_list     ap;
  46. classEntry *    clsEnt;
  47. superEntry *    parent;
  48. char *        objDef;
  49. int        class;
  50. int        x;
  51. object        newInst;
  52.  
  53. if(instance!=Object) /* not explicit call ? */
  54.     {
  55.     /* we must take the place of a missing kill routine */
  56.     if(NULL==(objDef=getObjDef((tag) instance)))
  57.     {
  58.     g(Err)(Object,instance,gcerrmsg[ERR_BAD_HANDLE]);
  59.     goto end;
  60.     }
  61.     objDef+=((objHndl *) &instance)->fext;
  62.     class=*((tag *) objDef);
  63.     if(NULL==(clsEnt=getObjDef(class)))
  64.     {
  65.     g(Err)(Object,(object) class,gcerrmsg[ERR_BAD_CLASS-
  66.         FIRST_GCOOPE_ERROR]);
  67.     goto end;
  68.     }
  69.     (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
  70.     for(x=clsEnt->numSuper;x>0;x--,parent++)
  71.     {
  72.     newInst=instance;
  73.     ((objHndl *) &newInst)->fext+=parent->offset;
  74.     g(Kill)(newInst);
  75.     }
  76.     }
  77. else
  78.     {
  79.     va_start(ap, instance);
  80.     instance=va_arg(ap, object);
  81.     va_end(ap);
  82.     if(NULL==(objDef=getObjDef((tag) instance)))
  83.     {
  84.     g(Err)(Object, instance,gcerrmsg[ERR_BAD_HANDLE-
  85.         FIRST_GCOOPE_ERROR]);
  86.     goto end;
  87.     }
  88.     }
  89. if(instance>=0 && ((objHndl *) &instance)->fext) goto end; /* not owner */
  90. rmvObject((tag) instance);
  91. if(instance<0) goto end; /* no iv block */
  92. s_free(objDef);
  93. return (object) objDef;
  94.  
  95. end:
  96. return (object) NULL;
  97. }
  98.  
  99.  
  100. typedef union {
  101.     unsigned int     hex[32];
  102.     unsigned char    ascii[64];
  103.     } stackDump;
  104.  
  105.  
  106. /*
  107. AVAILABLE AS DEFAULT Err ROUTINE.
  108.  
  109.     This routine prints out on stderr all the currently available
  110.     information (including a stack dump) concerning the error encountered.
  111.     It then terminates the program via. abort.
  112. */
  113.  
  114. static object err(object instance,...)
  115. {
  116. va_list        ap;
  117. int             xcall=0;
  118. char *        objDef;
  119. classEntry *    clsEnt;
  120. int        x,y;
  121. stackDump *    dump;
  122.  
  123. va_start(ap, instance);
  124. if(instance==Object)
  125.    {
  126.    xcall=1;
  127.    instance=va_arg(ap, object);
  128.    }
  129. fprintf(stderr,"\nRun time error - GCOOPE Version 1.0 SDK kernel:\n");
  130. fprintf(stderr,"Passed handle: %p \n",(void *) instance);
  131. if(!xcall)
  132.     fprintf(stderr,"Undefined error; probable bad alias for generic\n");
  133. else
  134.     {
  135.     if(instance!=Object)
  136.     {
  137.     objDef=getObjDef((tag) instance);
  138.     if(objDef==NULL) fprintf(stderr,"Bad calling instance \n");
  139.     else
  140.         {
  141.         objDef+=((objHndl *) instance)->fext;
  142.         clsEnt=getObjDef(*((tag *) objDef));
  143.         if(clsEnt==NULL) fprintf(stderr,"Bad instance class \n");
  144.         else fprintf(stderr,"Calling class: %x \n",(tag) instance);
  145.         }
  146.     }
  147.     else fprintf(stderr,"Called by kernel function \n");
  148.     fprintf(stderr,"Error Message: %s \n",va_arg(ap,char *));
  149.     }
  150. va_end(ap);
  151. fprintf(stderr,"Stack Dump:");
  152. va_start(ap, instance);
  153. dump=(stackDump *) ap;
  154. dump++;
  155. for(x=0,y=-1;x<32;)
  156.     {
  157.     fprintf(stderr,"\n\t%04x %04x %04x %04x  %c%c%c%c%c%c%c%c",
  158.      dump->hex[x++], dump->hex[x++], dump->hex[x++], dump->hex[x++],
  159.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  160.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  161.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  162.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  163.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  164.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  165.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y],
  166.      (iscntrl(dump->ascii[++y]))?'.':dump->ascii[y]);
  167.     }
  168. va_end(ap);
  169. fprintf(stderr,"\n");
  170. abort();
  171. return (object) NULL;
  172. }
  173.  
  174.  
  175. /*
  176.     The following default method returns the class of the CURRENT
  177.     instance.  If you want the owning class then for non flag class
  178.     instances you must set the fext field to zero.
  179.  
  180.     Note: this routine may be called by passing Object as the inst
  181.     parm, in that case, the instance is first variable argument parm.
  182. */
  183.  
  184.  
  185. static object getClassOf(object inst,...)
  186. {
  187. object        class=0;
  188. char *        objClass;
  189. va_list        ap;
  190.  
  191. va_start(ap, inst);
  192. if(inst==Object) inst=va_arg(ap, object);
  193. va_end(ap);
  194.  
  195. if(inst>=0)
  196.     {
  197.     if(NULL==(objClass=getObjDef((tag) inst))) goto end;
  198.     objClass+=((objHndl *) &inst)->fext;
  199.     (tag) class = *((tag *) objClass);
  200.     }
  201. else
  202.     {
  203.     (tag) class = ((objHndl *) &inst)->fext & SIGNMASK;
  204.     }
  205.  
  206. end:
  207. return class;
  208. }
  209.  
  210.  
  211. /*
  212.     This default method returns the size of the instance variable
  213.     structure for the current instance.  It may be called with Object
  214.     as the first parameter in which case the actual instance is the
  215.     first variable argument parameter.
  216.  
  217. */
  218.  
  219. static object getIVsize(object inst,...)
  220. {
  221. object        retVal=-1;
  222. tag *         clsNdx;
  223. classEntry *    clsEnt;
  224. va_list        ap;
  225.  
  226. va_start(ap, inst);
  227. if(inst==Object) inst=va_arg(ap,object);
  228. va_end(ap);
  229.  
  230. if(inst<0)
  231.     {
  232.     if(NULL==(clsEnt=getObjDef(SIGNMASK & ((objHndl *) &inst)->fext)))
  233.     goto end;
  234.     }
  235. else
  236.     {
  237.     if(NULL==(clsNdx=getIVptr(inst))) goto end;
  238.     if(NULL==(clsEnt=getObjDef(clsNdx[-1]))) goto end;
  239.     }
  240. retVal=(object) clsEnt->ivSize;
  241.  
  242. end:
  243. return retVal;
  244. }
  245.  
  246. /*
  247.     This default method allows you to see if an instance responds
  248.     to a given generic function without calling via g and causing
  249.     an error.  The instance parameter may be equal to Object, in that
  250.     case the actual instance is the first variable argument parameter.
  251.     In any case the first variable argument parameter after the actual
  252.     instance is of type generic and is the generic function index.
  253. */
  254.  
  255. static object defRespondsTo(object instance,...)
  256. {
  257. object         class;
  258. generic     genFunc;
  259. va_list        ap;
  260.  
  261. va_start(ap,instance);
  262. if(instance==Object) instance = va_arg(ap, object);
  263. genFunc=va_arg(ap, generic);
  264. va_end(ap);
  265.  
  266. class=getClassOf(instance);
  267. return (object) getMthd(genFunc, (tag)class);
  268. }
  269.  
  270.  
  271. /*
  272.  
  273.     This default method performs a full (or deep) copy function.
  274.     The instance parm is the object to be copied, this method will return
  275.     an object handle to a new instance that is an exact duplicate of the
  276.     old.  If the instance is of class Class, this method will return 0.
  277.  
  278.     If the instance parm is equal to Object, the actual instance is
  279.     the first variable argument parameter.
  280.  
  281.     For instances of classes that maintain a dynamically allocated
  282.     memory area as part of their instance data, a class method for deepCopy
  283.     should be defined that correctly creates and copies a new dynamically
  284.     allocated area for the newly created object instance.
  285.  
  286. */
  287.  
  288.  
  289. static object defDeepCopy(object instance,...)
  290. {
  291. object        newObj=0;
  292. object        class;
  293. tag        oldfext;
  294. objectEntry *    objEnt;
  295. classEntry *    clsEnt;
  296. void *        newInst;
  297. void *        oldInst;
  298. va_list        ap;
  299.  
  300. va_start(ap,instance);
  301. if(instance==Object) instance=va_arg(ap, object);
  302. va_end(ap);
  303.  
  304. if(instance<0)
  305.     {
  306.     newObj=instance;
  307.     goto end;
  308.     }
  309. if(Class==(class=getClassOf(instance))) goto end;
  310. if(NULL==(clsEnt=getObjDef((tag) class))) goto end;
  311. oldfext=((objHndl *) &instance)->fext;
  312. ((objHndl *) &instance)->fext=0;
  313. if(NULL==(objEnt=getObject((tag) instance))) goto end;
  314. if(NULL==(oldInst=objEnt->objDef)) goto end;
  315. newInst=s_malloc(clsEnt->totSize);
  316. memcpy(newInst, oldInst, clsEnt->totSize);
  317. if((newObj=addObject(newInst, objEnt->procID))<0) goto err;
  318. ((objHndl *) &newObj)->fext=oldfext;
  319.  
  320. end:
  321. return newObj;
  322.  
  323. err:
  324. s_free(newInst);
  325. return 0;
  326. }
  327.  
  328.  
  329. /*
  330.     This default method performs a shallow copy function.  In this
  331.    method, only the current instance portion of the source instance is
  332.    copied to the destination instance.  The source parameter is of type
  333.    object and is the variable argument parameter immeadiately following
  334.    the actual destin parameter.  This method will return 0 on error and
  335.    will not copy an instance of class Class.
  336.  
  337.     Note: This method may be called with destin==Object, in that
  338.    case the actual destin parameter is the first variable argument parm
  339.    and the source is the second variable argument parm.
  340.  
  341.     As with deepCopy above, classes that use dynamically allocated
  342.    memory areas as part of their instance variables should define a
  343.    method for this generic that correctly copies those areas.
  344.  
  345. */
  346.  
  347. static object defShallowCopy(object destin,...)
  348. {
  349. object         retVal=0;
  350. object        source;
  351. object        srcClass;
  352. void *        destIV;
  353. void *        srcIV;
  354. int        size;
  355. va_list        ap;
  356.  
  357. va_start(ap,destin);
  358. if(destin==Object) destin=va_arg(ap, object);
  359. source=va_arg(ap, object);
  360. va_end(ap);
  361.  
  362. if((srcClass=getClassOf(source))<0) goto end;
  363. if(srcClass==Class) goto end;
  364. if((getClassOf(destin)!=srcClass) &&
  365.     (0==(destin=steer(srcClass, destin)))) goto end;
  366. size = (int) getIVsize(source);
  367. if(destin<0)
  368.     {
  369.     if(source<0) return destin=source;
  370.     if(NULL==(srcIV=getIVptr(source))) goto end;
  371.     switch(size) {
  372.     case sizeof(byte)  : (byte) destin = *((byte *) srcIV);break;
  373.     case sizeof(short) : (short) destin = *((short *) srcIV); break;
  374. #if sizeof(short)!=sizeof(int)
  375.     case sizeof(int)   : (int) destin = *((int *) srcIV); break;
  376. #endif
  377.     default           : goto end;
  378.     }
  379.     }
  380. else
  381.     {
  382.     if(NULL==(destIV=getIVptr(destin))) goto end;
  383.     if(source<0)
  384.     {
  385.     switch(size) {
  386.         case sizeof(byte)  : *((byte *) destIV) = (byte) source; break;
  387.         case sizeof(short) : *((short *) destIV) = (short) source; break;
  388. #if sizeof(short)!=sizeof(int)
  389.         case sizeof(int)   : *((int *) destIV) = (int) source; break;
  390. #endif
  391.         default           : goto end;
  392.         }
  393.     }
  394.     else
  395.     {
  396.     if(NULL==(srcIV=getIVptr(source))) goto end;
  397.     memcpy(destIV, srcIV, size);
  398.     }
  399.     }
  400. retVal=destin;
  401.  
  402. end:
  403. return retVal;
  404. }
  405.  
  406.  
  407.  
  408. /*
  409. FOR KERNEL USE ONLY.
  410.  
  411.     This routine installs the pseudo-class Object and initializes the
  412.     main generic functions.
  413. */
  414.  
  415. stat Object_Install(void)
  416. {
  417. stat            ret=FUNCFAIL;
  418.  
  419. /* first add the Object definition to the objList and the name to symList */
  420.  
  421. Object=(object) 0L;
  422. if((((objHndl *) &Object)->tag=addObject(&obj,PERM_PROC_ID))<0) goto end;
  423.  
  424. /* now initialize the generic functions */
  425.  
  426. if(MAX_GEN==(New=addGeneric((method) NULL))) goto end;
  427. if(MAX_GEN==(Kill=addGeneric(kill))) goto end;
  428. if(MAX_GEN==(Err=addGeneric(err))) goto end;
  429. if(MAX_GEN==(GFclassOf=addGeneric(getClassOf))) goto end;
  430. if(MAX_GEN==(GFivSize=addGeneric(getIVsize))) goto end;
  431. if(MAX_GEN==(GFrespondsTo=addGeneric(defRespondsTo)))
  432.     goto end;
  433. if(MAX_GEN==(GFdeepCopy=addGeneric(defDeepCopy))) goto end;
  434. if(MAX_GEN==(GFshallowCopy=addGeneric(defShallowCopy)))
  435.     goto end;
  436.  
  437.  
  438. ret=FUNCOKAY;
  439.  
  440. end:
  441. return ret;
  442. }
  443.  
  444.  
  445.  
  446.